/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * PLCEmulator.java
 *
 * Created on May 12, 2011, 2:01:00 PM
 */
package plc;

import MyPackage.Button;
import MyPackage.Command;
import MyPackage.Condition;
import MyPackage.Device;
import MyPackage.Function;
import MyPackage.MyTimer;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

/**
 *
 * @author PhatChai
 */
public class PLCEmulator extends javax.swing.JFrame {

    private static final String DEVICE_HEADER[] = {"Device Name", "Status", "Watt"};
    private static final int DEVICE_NAME_COLUMN = 0;
    private static final int DEVICE_STATUS_COLUMN = 1;
    private static final int DEVICE_WATT_COLUMN = 2;
    private PLCController controller;
    /**
     * table model for devices.
     */
    TableModel deviceModel;
    /**
     * List of active Devices.
     */
    private List<Device> deviceList;
    private List<Function> functionList;
    private Thread summaryThread;
    private double wattUsage = 0;

    /** Creates new form PLCEmulator */
    public PLCEmulator() {
        initComponents();
    }

    public PLCEmulator(PLCController c, List<Device> dList, List<Function> fList) {
        this();
        controller = c;
        deviceList = dList;
        functionList = fList;
    }

    public void createButton(Button b) {
        JButton button = new JButton(b.label);

        button.addActionListener(new ButtonListener(b.command_list));

        remotePane.add(button);
    }

    public void createSchedule(MyTimer t) {
        JLabel label = new JLabel(t.timeStr);

//        Timer t = new Timer();
//        t.scheduleAtFixedRate(new TimerTask() {
//
//            @Override
//            public void run() {
//                throw new UnsupportedOperationException("Not supported yet.");
//            }
//        }, new Date(), 1);

//        timerPane.add(label);
    }

    public void updateSummary(double wattUsage, double unit, double currentCost,Device d) {
        NumberFormat df = new DecimalFormat("0.000");
        lblWattUsage.setText(df.format(wattUsage));
        lblUnits.setText(df.format(unit));
        lblCurrentCost.setText(df.format(currentCost));
        lblMostPowerDevice.setText(d.name);
        lblMostWattConsume.setText(df.format(d.wattUsage));
    }

    /**
     * Create Summary update thread running every one second.
     * - update watt usage
     * - update current cost
     */
    public void createSummryUpdateThread(final double elecCost) {
        summaryThread = new Thread(new Runnable() {

            @Override
            public void run() {
                double cost = elecCost;
                wattUsage = 0;
                double unit = 0;
                double currentCost = 0;
                // infinite loop
                double maxDeviceWattUsage=0.0;
                Device maxDevice=new Device();
                maxDevice.name = "";
                maxDevice.wattUsage=0.0;
                while (true) {

                    // watt usage in one second
                    double w = 0;
                    // get current watt usage from all on devices.
                    for (Device d : deviceList) {
                        if (d.status == Device.ON) {
//                            editor.output("Device on: " + d.name);
                            // watt usage in one second
                            w += (double) d.watt / 3600;

                            d.wattUsage+=(double) d.watt / 3600;
                            if(d.wattUsage > maxDeviceWattUsage){
                                maxDeviceWattUsage=d.wattUsage;
                                maxDevice = d;
                            }
                        }
                        System.out.println("Device : "+d.name+" Watt Usage : "+d.wattUsage);
                    }
                    System.out.println("Device consume most power : "+maxDevice.name+" Watt Usage : "+maxDevice.wattUsage);

                    wattUsage += w;

                    unit = wattUsage / 1000;

                    currentCost = unit * cost;
                    updateSummary(wattUsage, unit, currentCost,maxDevice);
                    updateUI();

//                    System.out.println("current cost: " + currentCost);
                    // delay for one second.
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        });
        summaryThread.start();
    }

    public void initDevicePane(int numDevice) {
        deviceModel = new DeviceTableModel(numDevice, DEVICE_HEADER);
        tblDevice.setModel(deviceModel);
    }

    public void createDevice(int row, Device device) {
        deviceModel.setValueAt(device.name, row, 0);
        deviceModel.setValueAt(device.status, row, 1);
        deviceModel.setValueAt(device.watt, row, 2);
    }

    private boolean checkConditions(List<Condition> condition_list) {
        boolean result = true;
        boolean r = true;
        StringBuilder sB = new StringBuilder();
        sB.append("if ");
        int size = condition_list.size();
        int i = 0;
        for (Condition cond : condition_list) {
            if (size > 1 && i > 0) {
                sB.append(cond.and_or_op == Condition.AND? " and ": " or ");
            }
            // check condition type
            if (cond.type == Condition.CHECK_DEVICE_ON_OFF) {
                int status = findDeviceByName(cond.device_name).status;
                r = status == cond.check_on_off;
                sB.append(cond.device_name);
                sB.append(" is ");
                sB.append(cond.check_on_off == Condition.ON? "On ": "Off ");
            } else if (cond.type == Condition.CHECK_TOTAL_WATT_USAGE) {
                String rel = cond.compare_op;
                if (rel.equals("<")) {
                    r = wattUsage < cond.number_to_compare;
                } else if (rel.equals(">")) {
                    r = wattUsage > cond.number_to_compare;
                } else if (rel.equals(">=")) {
                    r = wattUsage >= cond.number_to_compare;
                } else if (rel.equals("<=")) {
                    r = wattUsage <= cond.number_to_compare;
                } else if (rel.equals("=")) {
                    r = wattUsage == cond.number_to_compare;
                }
                sB.append("Watt Usage ");
                sB.append(rel);
                sB.append(" ");
                sB.append(cond.number_to_compare);
            }

            // concatinate all conditions
            if (cond.and_or_op == Condition.AND) {
                result &= r;

            } else if (cond.and_or_op == Condition.OR) {
                result |= r;
            }
            i++;
        }
        output(sB.toString());
        return result;
    }

    class DeviceTableModel extends AbstractTableModel {

        private Hashtable lookup;
        private final int rows;
        private final int columns;
        private final String headers[];

        public DeviceTableModel(int rows, String columnHeaders[]) {
            if ((rows < 0) || (columnHeaders == null)) {
                throw new IllegalArgumentException(
                        "Invalid row count/columnHeaders");
            }
            this.rows = rows;
            this.columns = columnHeaders.length;
            headers = columnHeaders;
            lookup = new Hashtable();
        }

        public int getColumnCount() {
            return columns;
        }

        public int getRowCount() {
            return rows;
        }

        public String getColumnName(int column) {
            return headers[column];
        }

        public Object getValueAt(int row, int column) {
            return lookup.get(new Point(row, column));
        }

        public void setValueAt(Object value, int row, int column) {
            if ((rows < 0) || (columns < 0)) {
                throw new IllegalArgumentException("Invalid row/column setting");
            }
            if ((row < rows) && (column < columns)) {
                // Update device object in the device list.
                Device d = deviceList.get(row);
                if (column == DEVICE_NAME_COLUMN) {
                    lookup.put(new Point(row, column), value);
                    d.name = (String) value;
                } else if (column == DEVICE_STATUS_COLUMN) {
                    int status = Integer.parseInt(value + "");
                    lookup.put(new Point(row, column), (status == 1 ? "On" : "Off"));
                    d.status = status;
                } else if (column == DEVICE_WATT_COLUMN) {
                    lookup.put(new Point(row, column), value);
                    d.watt = Integer.parseInt(value + "");
                }
            }
        }
    }

    public void setWattHour(int watt) {
        lblWatt.setText(watt + "");
    }

    public void output(String message) {
        txtConsole.append(message + "\n");
    }

    /**
     * refresh the emulator
     */
    public void updateUI() {
        // update device table
        tblDevice.updateUI();

        summaryPane.updateUI();
    }

    public void doCommands(List<Command> cList) {
        if (cList != null) {
            for (Command c : cList) {
                // check comand type
                if (c.type == Command.REGULAR_COMMAND) {
                    doCommand(c);
                } else if (c.type == Command.IF_COMMAND) {
                    boolean result = checkConditions(c.condition_list);

                    // check condition result
                    if (result) {
                        doCommands(c.command_list1);
                    } else {
                        doCommands(c.command_list2);
                    }
                } else if (c.type == Command.FUNC_COMMAND) {
                    Function f = findFunctionByName(c.func_name);
                    output("call function: " + f.name);
                    doCommands(f.command_list);
                }
            }
            updateUI();
        }
    }

    private void doCommand(Command c) {
        deviceModel.setValueAt(c.command, findDeviceIndexByName(c.device_name), DEVICE_STATUS_COLUMN);
        output(c.device_name + " " + (c.command == Command.ON ? " On " : " Off "));
    }

    private int findDeviceIndexByName(String device_name) {
        int i = 0;

        for (Device d : deviceList) {
            if (d.name.equals(device_name)) {
                return i;
            }
            i++;
        }
        return -1;
    }

    private Device findDeviceByName(String device_name) {
        int i = 0;

        for (Device d : deviceList) {
            if (d.name.equals(device_name)) {
                return d;
            }
            i++;
        }
        return null;
    }

    private Function findFunctionByName(String functionName) {
        int i = 0;

        for (Function f : functionList) {
            if (f.name.equals(functionName)) {
                return f;
            }
            i++;
        }
        return null;
    }

    private class ButtonListener implements ActionListener {

        List<Command> cList;

        public ButtonListener(List<Command> cList) {
            this.cList = cList;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JButton button = (JButton) e.getSource();

            output("button clicked: " + button.getText() + " ");
            doCommands(cList);
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel2 = new javax.swing.JPanel();
        jScrollPane4 = new javax.swing.JScrollPane();
        remotePane = new javax.swing.JPanel();
        consolePane = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        txtConsole = new javax.swing.JTextArea();
        devicePane = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblDevice = new javax.swing.JTable();
        summaryPane = new javax.swing.JPanel();
        lblWatt = new javax.swing.JLabel();
        lblWattUsage = new javax.swing.JLabel();
        lblUnits = new javax.swing.JLabel();
        lblCurrentCost = new javax.swing.JLabel();
        lblMostPowerDevice = new javax.swing.JLabel();
        lblMostWattConsume = new javax.swing.JLabel();
        lblWatt1 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("PLC Emulator");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(870, 552));
        setName("PLC Emulator"); // NOI18N
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                formWindowClosed(evt);
            }
        });

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Remote Control"));
        jPanel2.setName("jPanel2"); // NOI18N

        jScrollPane4.setBorder(null);
        jScrollPane4.setName("jScrollPane4"); // NOI18N

        remotePane.setMaximumSize(new java.awt.Dimension(240, 32767));
        remotePane.setMinimumSize(new java.awt.Dimension(240, 37));
        remotePane.setName("remotePane"); // NOI18N
        remotePane.setPreferredSize(new java.awt.Dimension(240, 10));
        remotePane.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
        jScrollPane4.setViewportView(remotePane);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 241, Short.MAX_VALUE)
            .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 501, Short.MAX_VALUE)
            .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup()
                    .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 490, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );

        consolePane.setBorder(javax.swing.BorderFactory.createTitledBorder("Console"));
        consolePane.setName("consolePane"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        txtConsole.setColumns(20);
        txtConsole.setEditable(false);
        txtConsole.setRows(5);
        txtConsole.setName("txtConsole"); // NOI18N
        jScrollPane2.setViewportView(txtConsole);

        javax.swing.GroupLayout consolePaneLayout = new javax.swing.GroupLayout(consolePane);
        consolePane.setLayout(consolePaneLayout);
        consolePaneLayout.setHorizontalGroup(
            consolePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(consolePaneLayout.createSequentialGroup()
                .addGap(0, 1, Short.MAX_VALUE)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 727, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 10, Short.MAX_VALUE))
        );
        consolePaneLayout.setVerticalGroup(
            consolePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(consolePaneLayout.createSequentialGroup()
                .addGap(0, 1, Short.MAX_VALUE)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 235, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 11, Short.MAX_VALUE))
        );

        devicePane.setBorder(javax.swing.BorderFactory.createTitledBorder("Device"));
        devicePane.setName("devicePane"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        tblDevice.setName("tblDevice"); // NOI18N
        jScrollPane1.setViewportView(tblDevice);

        javax.swing.GroupLayout devicePaneLayout = new javax.swing.GroupLayout(devicePane);
        devicePane.setLayout(devicePaneLayout);
        devicePaneLayout.setHorizontalGroup(
            devicePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(devicePaneLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 367, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        devicePaneLayout.setVerticalGroup(
            devicePaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(devicePaneLayout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 204, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(12, Short.MAX_VALUE))
        );

        summaryPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Summary"));
        summaryPane.setName("summaryPane"); // NOI18N

        lblWatt.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblWatt.setText(" ");
        lblWatt.setName("lblWatt"); // NOI18N

        lblWattUsage.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblWattUsage.setText(" ");
        lblWattUsage.setName("lblWattUsage"); // NOI18N

        lblUnits.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblUnits.setText(" ");
        lblUnits.setName("lblUnits"); // NOI18N

        lblCurrentCost.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblCurrentCost.setText(" ");
        lblCurrentCost.setName("lblCurrentCost"); // NOI18N

        lblMostPowerDevice.setName("lblMostPowerDevice"); // NOI18N

        lblMostWattConsume.setName("lblMostWattConsume"); // NOI18N

        lblWatt1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblWatt1.setText(" ");
        lblWatt1.setName("lblWatt1"); // NOI18N

        jLabel1.setText("Electricity cost:");
        jLabel1.setName("jLabel1"); // NOI18N

        jLabel2.setText("THB per Unit");
        jLabel2.setName("jLabel2"); // NOI18N

        jLabel3.setText("Watt usage:");
        jLabel3.setName("jLabel3"); // NOI18N

        jLabel4.setText("Current cost:");
        jLabel4.setName("jLabel4"); // NOI18N

        jLabel5.setText("Watts");
        jLabel5.setName("jLabel5"); // NOI18N

        jLabel6.setText("Units");
        jLabel6.setName("jLabel6"); // NOI18N

        jLabel7.setText("THB");
        jLabel7.setName("jLabel7"); // NOI18N

        jLabel8.setText("Device consume most power:");
        jLabel8.setName("jLabel8"); // NOI18N

        jLabel9.setText("Watt usage of most consume power device:");
        jLabel9.setName("jLabel9"); // NOI18N

        javax.swing.GroupLayout summaryPaneLayout = new javax.swing.GroupLayout(summaryPane);
        summaryPane.setLayout(summaryPaneLayout);
        summaryPaneLayout.setHorizontalGroup(
            summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(summaryPaneLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(summaryPaneLayout.createSequentialGroup()
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addGroup(summaryPaneLayout.createSequentialGroup()
                                    .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jLabel1)
                                        .addComponent(jLabel3))
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                    .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(lblWattUsage, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(lblWatt, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                .addGroup(summaryPaneLayout.createSequentialGroup()
                                    .addComponent(jLabel4)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(lblCurrentCost, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(lblUnits, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(18, 18, 18)
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(summaryPaneLayout.createSequentialGroup()
                                .addComponent(jLabel7)
                                .addContainerGap(75, Short.MAX_VALUE))
                            .addGroup(summaryPaneLayout.createSequentialGroup()
                                .addComponent(jLabel5)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(lblWatt1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGap(227, 227, 227))
                            .addGroup(summaryPaneLayout.createSequentialGroup()
                                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel6)
                                    .addComponent(jLabel2))
                                .addContainerGap())))
                    .addGroup(summaryPaneLayout.createSequentialGroup()
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, summaryPaneLayout.createSequentialGroup()
                                .addComponent(jLabel9)
                                .addGap(18, 18, 18)
                                .addComponent(lblMostWattConsume, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, summaryPaneLayout.createSequentialGroup()
                                .addComponent(jLabel8)
                                .addGap(18, 18, 18)
                                .addComponent(lblMostPowerDevice, javax.swing.GroupLayout.PREFERRED_SIZE, 142, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addContainerGap())))
        );

        summaryPaneLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {lblCurrentCost, lblWatt, lblWattUsage});

        summaryPaneLayout.setVerticalGroup(
            summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(summaryPaneLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(summaryPaneLayout.createSequentialGroup()
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel6)
                            .addComponent(lblUnits)))
                    .addGroup(summaryPaneLayout.createSequentialGroup()
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel1)
                            .addComponent(lblWatt))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel3)
                            .addComponent(lblWatt1)
                            .addComponent(lblWattUsage))
                        .addGap(20, 20, 20)))
                .addGap(5, 5, 5)
                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(jLabel4)
                    .addComponent(lblCurrentCost))
                .addGap(30, 30, 30)
                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel8)
                    .addComponent(lblMostPowerDevice, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(summaryPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel9)
                    .addComponent(lblMostWattConsume, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(68, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(devicePane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(summaryPane, javax.swing.GroupLayout.PREFERRED_SIZE, 332, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(consolePane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(consolePane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(summaryPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(devicePane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
        summaryThread.interrupt();
    }//GEN-LAST:event_formWindowClosed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel consolePane;
    private javax.swing.JPanel devicePane;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JLabel lblCurrentCost;
    private javax.swing.JLabel lblMostPowerDevice;
    private javax.swing.JLabel lblMostWattConsume;
    private javax.swing.JLabel lblUnits;
    private javax.swing.JLabel lblWatt;
    private javax.swing.JLabel lblWatt1;
    private javax.swing.JLabel lblWattUsage;
    private javax.swing.JPanel remotePane;
    private javax.swing.JPanel summaryPane;
    private javax.swing.JTable tblDevice;
    private javax.swing.JTextArea txtConsole;
    // End of variables declaration//GEN-END:variables
}
